package AneRouge;
import java.applet.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;

public class AneRouge extends Applet implements MouseListener,
		MouseMotionListener, Runnable {
	final static int delay = 30;

	final static int repaint = 1;

	final static int moving = 2;

	final static int win = 3;

	final static int edge = 80;

	final static int sideX = 512;

	final static int sideY = 600;

	final static int playX = 320;

	final static int playY = 400;

	final static int border = 32;

	final static int buttonX = 5 * edge;

	final static int buttonY = 3 * edge;

	final static int buttonRay = (border / 2) * 3;

	final static int panelX = 4 * edge + 2 * border;

	final static int panelY = edge;

	final static int panelWidth = 2 * (edge - border);

	final static int panelHeight = 2 * border;

	final static int empty = -2;

	final static int wall = -1;

	final static int numBloc = 10;

	final static int blocDX[] = { 1, 2, 1, 1, 2, 1, 1, 1, 1, 1 };

	final static int blocDY[] = { 2, 2, 2, 2, 1, 2, 1, 1, 1, 1 };

	final static int blocIPX[] = { 1, 2, 4, 1, 2, 4, 2, 3, 1, 4 };

	final static int blocIPY[] = { 1, 1, 1, 3, 3, 3, 4, 4, 5, 5 };

	final static int dirX[] = { -1, 0, 1, 0 };

	final static int dirY[] = { 0, 1, 0, -1 };

	Color couleurFond;

	Image offImage, playImage, boardImage, carrotsImage;

	Graphics offGraphics, playGraphics;

	int board[][], blocX[], blocY[], blocWidth[], blocHeight[];

	int blocPX[], blocPY[], blocIX[], blocIY[];

	int drawMode, movingBloc, hpx, hpy, hx, hy;

	int lastMoving, lastX, lastY, step;

	int stringX, stringY;

	MediaTracker tracker;

	Thread thread;

	boolean canMove(int n, int dir) {
		boolean can = true;
		if (dir >= 0 && dir < 4)
			can = isClear(blocPX[n] + dirX[dir], blocPY[n] + dirY[dir],
					blocDX[n], blocDY[n]);
		return can;
	}

	void clearBoard() {
		for (int i = 0; i < 6; i++)
			for (int j = 0; j < 7; j++)
				if (i == 0 || i == 5 || j == 0 || j == 6)
					board[i][j] = wall;
				else
					board[i][j] = empty;
	}

	void eraseBloc(int n) {
		for (int i = 0; i < blocDX[n]; i++)
			for (int j = 0; j < blocDY[n]; j++)
				board[blocPX[n] + i][blocPY[n] + j] = empty;
	}

	public String getAppletInfo() {
		return "AneRouge\n" + "\n" + "Copyright (c) 1999 by Gross� Pascal\n"
				+ "";
	}

	public void init() {
		super.init();
		addMouseListener(this);
		addMouseMotionListener(this);
		try {
			int r = Integer.parseInt(getParameter("Red"));
			int v = Integer.parseInt(getParameter("Green"));
			int b = Integer.parseInt(getParameter("Blue"));
			couleurFond = new Color(r, v, b);
		} catch (NumberFormatException e) {
			couleurFond = Color.lightGray;
		}
		;
		offImage = createImage(sideX, sideY);
		offGraphics = offImage.getGraphics();
		offGraphics.setColor(Color.black);
		offGraphics.fillRect(0, 0, sideX, sideY);
		Font font = new Font("Courier", Font.BOLD, 14);
		FontMetrics fm = offGraphics.getFontMetrics(font);
		offGraphics.setFont(font);
		stringX = ((panelWidth - fm.stringWidth("Step XXX")) / 2) + panelX;
		stringY = ((panelHeight + fm.getAscent()) / 2) + panelY;
		playImage = createImage(sideX + playX, sideY);
		playGraphics = playImage.getGraphics();
		playGraphics.setColor(Color.black);
		playGraphics.fillRect(0, 0, sideX + playX, sideY);
		tracker = new MediaTracker(this);
		boardImage = getImage(getCodeBase(), "Board.gif");
		tracker.addImage(boardImage, 0);
		Image setImage = getImage(getCodeBase(), "Set.gif");
		tracker.addImage(setImage, 1);
		carrotsImage = getImage(getCodeBase(), "Carrots.gif");
		tracker.addImage(carrotsImage, 1);
		try {
			tracker.waitForAll();
		} catch (InterruptedException e) {
		}
		;
		playGraphics.drawImage(setImage, sideX, border, this);
		board = new int[numBloc + 2][numBloc + 2];
		blocX = new int[numBloc];
		blocY = new int[numBloc];
		blocIX = new int[numBloc];
		blocIY = new int[numBloc];
		blocPX = new int[numBloc];
		blocPY = new int[numBloc];
		blocWidth = new int[numBloc];
		blocHeight = new int[numBloc];
		resize(sideX, sideY);
	}

	boolean isClear(int px, int py, int dx, int dy) {
		boolean clear = true;
		for (int i = 0; i < dx && clear; i++)
			for (int j = 0; j < dy && clear; j++)
				if (board[px + i][py + j] != empty
						&& board[px + i][py + j] != movingBloc)
					clear = false;
		return clear;
	}

	public void mouseClicked(MouseEvent e) {
	}

	public void mouseDragged(MouseEvent e) {
		if (drawMode == moving) {
			int x = e.getX() - border;
			int y = e.getY() - border;
			int npx = (x / edge) + 1;
			int npy = (y / edge) + 1;
			int dx = npx - hpx - blocPX[movingBloc];
			int dy = npy - hpy - blocPY[movingBloc];
			boolean stop = false;
			for (int dir = 0; dir < 4 && !stop; dir++)
				if ((dx * dirX[dir] > 0 || dy * dirY[dir] > 0)
						&& canMove(movingBloc, dir)) {
					eraseBloc(movingBloc);
					moveBlocTo(movingBloc, blocPX[movingBloc] + dirX[dir],
							blocPY[movingBloc] + dirY[dir]);
					repaint();
					stop = true;
				}
		}
	}

	public void mouseEntered(MouseEvent e) {
	}

	public void mouseExited(MouseEvent e) {
	}

	public void mouseMoved(MouseEvent e) {
	}

	public void mousePressed(MouseEvent e) {
		int x = e.getX() - border;
		int y = e.getY() - border;
		if (x >= 0 && x < playX && y >= 0 && y < playY) {
			int px = (x / edge) + 1;
			int py = (y / edge) + 1;
			movingBloc = board[px][py];
			if (movingBloc != empty && drawMode == repaint) {
				hpx = px - blocPX[movingBloc];
				hpy = py - blocPY[movingBloc];
				hx = x - blocX[movingBloc];
				hy = y - blocY[movingBloc];
				drawMode = moving;
				lastX = blocPX[movingBloc];
				lastY = blocPY[movingBloc];
			}
		}
		int xx = x - buttonX;
		int yy = y - buttonY;
		int dist2 = xx * xx + yy * yy;
		if (dist2 <= buttonRay * buttonRay) {
			drawMode = repaint;
			resetBoard();
			repaint();
		}
	}

	public void mouseReleased(MouseEvent e) {
		if (movingBloc < 0)
			return;
		if (lastX != blocPX[movingBloc] || lastY != blocPY[movingBloc]) {
			if (drawMode == moving && movingBloc == 1) {
				play(getCodeBase(), "Bray.au");
				if (blocPX[movingBloc] == 2 && blocPY[movingBloc] == 4) {
					drawMode = win;
				}
			}
			if (drawMode == moving && movingBloc != lastMoving) {
				step++;
				lastMoving = movingBloc;
				repaint();
			}
		}
		if (drawMode == moving)
			drawMode = repaint;
	}

	void moveBlocTo(int n, int px, int py) {
		blocPX[n] = px;
		blocPY[n] = py;
		blocX[n] = edge * (px - 1);
		blocY[n] = edge * (py - 1);
		for (int i = 0; i < blocDX[n]; i++)
			for (int j = 0; j < blocDY[n]; j++)
				board[i + px][j + py] = n;
	}

	public void paint(Graphics g) {
		g.drawImage(offImage, 0, 0, this);
	}

	void resetBoard() {
		clearBoard();
		for (int n = 0; n < numBloc; n++) {
			blocPX[n] = blocIPX[n];
			blocPY[n] = blocIPY[n];
			blocX[n] = edge * (blocPX[n] - 1);
			blocY[n] = edge * (blocPY[n] - 1);
			blocIX[n] = blocX[n];
			blocIY[n] = blocY[n];
			blocWidth[n] = edge * blocDX[n];
			blocHeight[n] = edge * blocDY[n];
			for (int i = 0; i < blocDX[n]; i++)
				for (int j = 0; j < blocDY[n]; j++)
					board[i + blocPX[n]][j + blocPY[n]] = n;
		}
		step = 0;
		lastMoving = empty;
		lastX = -1;
		lastY = -1;
	}

	public void run() {
		drawMode = repaint;
		resetBoard();
		repaint();
		while (thread != null) {
			try {
				thread.sleep(delay);
			} catch (InterruptedException e) {
			}
			if (drawMode == win) {
				repaint();
			}
		}
	}

	public void start() {
		if (thread == null) {
			thread = new Thread(this);
			thread.start();
		}
	}

	public void stop() {
		if (thread != null) {
			thread.stop();
			thread = null;
		}
	}

	public void update(Graphics g) {
		if (drawMode == win && blocY[1] < 400) {
			blocY[1] += 4;
		}
		playGraphics.drawImage(boardImage, 0, 0, this);
		for (int n = 0; n < numBloc; n++) {
			playGraphics.copyArea(blocIX[n] + sideX, blocIY[n] + border,
					blocWidth[n], blocHeight[n], -sideX + border - blocIX[n]
							+ blocX[n], -blocIY[n] + blocY[n]);
		}
		if (drawMode != win) {
			playGraphics.setColor(couleurFond);
			playGraphics.fillRect(0, 464, sideX, 600 - 464);
			playGraphics.drawImage(carrotsImage, border + edge + 10, edge * 5
					+ 2 * border - 10, this);
		}
		offGraphics.drawImage(playImage, 0, 0, this);
		offGraphics.setColor(new Color(10, 200, 130));
		if (drawMode != win)
			offGraphics.drawString("Step " + step, stringX, stringY);
		else
			offGraphics.drawString("You won!", stringX, stringY);
		g.drawImage(offImage, 0, 0, this);
	}
}
